﻿using System;
using System.Windows;
using PlottingBasics.Axis;
using System.Collections.Generic;

namespace PlottingBasics.Functions
{
    /// <summary>
    /// Helper class that applies a function to an axis. Rather than return a single set of values it returns
    /// the x,y point stream. Implemented as a iterator.
    /// </summary>
    public class ApplyFunction
    {
        class ApplyAxisToFunction : IEnumerable<Point>
        {
            private IAxis _axis;
            private Func<double, double> _toApply;

            /// <summary>
            /// Create the enumerable.
            /// </summary>
            /// <param name="axis"></param>
            /// <param name="toApply"></param>
            internal ApplyAxisToFunction(IAxis axis, Func<double, double> toApply)
            {
                this._axis = axis;
                this._toApply = toApply;
            }

            /// <summary>
            /// Enumerator that will zip this guy up until the axis runs out! :-)
            /// </summary>
            /// <returns></returns>
            public System.Collections.Generic.IEnumerator<Point> GetEnumerator()
            {
                foreach (var v in _axis)
                {
                    Point p = new Point() { X = v, Y = _toApply(v) };
                    yield return p;
                }
            }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// Returns an enumerable that will apply a function along an axis
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="toApply"></param>
        /// <returns></returns>
        public static IEnumerable<Point> Apply (IAxis axis, Func<double, double> toApply)
        {
            return new ApplyAxisToFunction(axis, toApply);
        }

    }
}
